#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define POLLFD_NUM  2

static void print_err(char *str, int line, int err_no) {
    if (str) printf("line %d %s: %s\n", line, str, strerror(err_no));
    exit(-1);
}

/**
 * poll示例:利用poll机制从阻塞文件(鼠标和键盘)读取数据, 并设置超时3秒
 * 鼠标光标坐标文件具体路径,需要先手动测试, 如cat /dev/input/mouse[0..3], 
 * 然后移动鼠标, 观察到有打印数据则为实际鼠标光标文件
 */
int main() {
    int ret;
    char buf1[100];
    int buf2 = 0;
    struct pollfd fds[POLLFD_NUM];

    // 具体是哪个mouse, 可以cat /dev/input/mouse? 进行测试
    int mousefd = open("/dev/input/mouse1", O_RDONLY); 
    if (mousefd < 0) print_err("open file fail", __LINE__, errno); 
    
    fds[0].fd = STDIN_FILENO; // 标准输入文件描述符,进程启动时已默认打开
    fds[0].events = POLLIN; // 请求事件

    fds[1].fd = mousefd;
    fds[1].events = POLLIN; // 请求事件

    while (1) {
        do {
//            ret = poll(fds, POLLFD_NUM, -1); // 第三个参数timeout = -1 无限期等待
              ret = poll(fds, POLLFD_NUM, 3000); // 超时时间3000ms
        }while(ret == -1 && errno == EINTR);

        if (ret > 0) { // 有动静的fd数量
            if (fds[0].events == fds[0].revents) {// 请求事件与返回的实际事件一致
                memset(buf1, 0, sizeof buf1);
                ret = read(fds[0].fd, buf1, sizeof buf1);
                if (ret > 0) printf("%s\n", buf1);
            }

            if (fds[1].events == fds[1].revents) {
                buf2 = 0;
                ret = read(fds[1].fd, &buf2, sizeof buf2); // 注意buf2是一个int变量,而非地址
                if (ret > 0) printf("%d\n", buf2);
            }
        }
        else if (ret == 0) printf("time out\n");
    }

    close(mousefd);

    return 0;
}


